//=====================================================================
//
//  File:      FetchRowsWithLargeUDTTypes.cpp
//  Summary:   Shows how to fetch rows with LargeUDT types from a result set.
//  Date:      October 1, 2008
//
//---------------------------------------------------------------------
//
//  This file is part of the Microsoft SQL Server Code Samples.
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF 
//ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
//THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//
//===================================================================== 

#include <stdio.h>
#include <tchar.h>
#include <stddef.h>
#include <windows.h>
#define ODBCVER 0x0350
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#define _SQLNCLI_ODBC
#include "sqlncli.h"

int main() {
   // The command to execute.
   SQLTCHAR* szCmdString = (SQLTCHAR *)_T("SELECT ID, LargeString FROM dbo.LargeStringUDTs");

   int ret = 0;
   SQLRETURN rc;
   SQLHENV hEnv = NULL;
   SQLHDBC hDbc = NULL;
   SQLHSTMT hStmt = NULL;
   SQLTCHAR szConn[256]; 
   BYTE DataBuf[15];
   SQLSMALLINT iLen = 0;
   SQLLEN iDataLen = 0;

   rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
   if (rc != SQL_SUCCESS) {
      printf("Failed to get HENV\n");
      return -1;
   }

   rc = SQLSetEnvAttr (hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
   if (rc != SQL_SUCCESS) {
      printf("Failed to SetEnvAttr\n");
      SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
      return -1;
   }

   rc = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
   if (rc != SQL_SUCCESS) {
      printf("Failed to get HDBC\n");
      SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
      return -1;
   }

   rc = SQLDriverConnect(hDbc, NULL, 
      (SQLTCHAR *)_T("DRIVER={SQL Server Native Client 10.0};SERVER=(local);Trusted_Connection=Yes;database=master"), 
      SQL_NTS, szConn, 255, &iLen, SQL_DRIVER_NOPROMPT);
   if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
      printf("Failed to connect\n");
      ret = -1;
      goto End;
   }

   rc = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
   if (rc != SQL_SUCCESS) {
      printf("Failed to get hstmt\n");
      ret = -1;
      goto End;
   }

   // Execute the command.
   rc = SQLExecDirect(hStmt, szCmdString, SQL_NTS);
   if (rc != SQL_SUCCESS) {
      printf("Failed to get hstmt\n");
      ret = -1;
      goto End;
   }

   // Process the result set.
   SQLSMALLINT paramType;
   SQLTCHAR szData[100], szData2[100];
   SQLSMALLINT NameLengthPtr = 0, DataTypePtr, DecimalDigitsPtr, NullablePtr;
   SQLULEN ColumnSizePtr[2];
   rc = SQLDescribeCol(hStmt, 1, szData, sizeof(szData), &NameLengthPtr, &DataTypePtr, &ColumnSizePtr[0], &DecimalDigitsPtr, &NullablePtr);
   _tprintf(_T("%s"), szData);
   rc = SQLDescribeCol(hStmt, 2, szData2, sizeof(szData2), &NameLengthPtr, &DataTypePtr, &ColumnSizePtr[1], &DecimalDigitsPtr, &NullablePtr);
   _tprintf(_T("          %s\n"), szData2);

   while ( ( rc = SQLFetch(hStmt ) ) == SQL_SUCCESS ) {
      rc = SQLGetData(hStmt, 1, SQL_C_SHORT, &paramType, sizeof(SQL_C_SHORT), NULL);
      printf("%d           ", paramType);

      bool ifFirst = true;
      while ( ( rc = SQLGetData(hStmt, 2 , SQL_C_BINARY, DataBuf, sizeof(DataBuf) ,&iDataLen ) ) != SQL_NO_DATA) {
         // process number of bytes in the DataBuf;
         int NumBytes = (iDataLen > sizeof(DataBuf)) || (iDataLen == SQL_NO_TOTAL) ? sizeof(DataBuf): iDataLen;
         for ( int i = ifFirst?5:0 ; i <NumBytes ; i++ )
            putchar((char)DataBuf[i]);
         ifFirst = false;
      };
      printf("\n");
   }

   if ( rc != SQL_NO_DATA ) {
      printf("Failed to fetch data\n");
      ret= -1;
   }

End:
   if (hStmt) {
      SQLFreeStmt(hStmt,SQL_CLOSE);
      SQLFreeStmt(hStmt,SQL_DROP);
   }

   if (hDbc) {
      SQLDisconnect(hDbc);
      SQLFreeConnect(hDbc);
   }

   if (hEnv)
      SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
};